<?php

/**
 * This is the model class for table "user".
 *
 * The followings are the available columns in table 'user':
 * @property integer $id
 * @property integer $rid
 * @property string $token
 * @property string $name
 * @property string $cnname
 * @property string $password
 * @property string $pwd_salt
 * @property string $status
 * @property string $mobile
 * @property string $company
 * @property string $last_login_time
 * @property string $last_login_ip
 * @property string $remark
 *
 * The followings are the available model relations:
 * @property Auth[] $auths
 * @property Bill[] $bills
 * @property Server[] $servers
 * @property Role $role
 */
class User extends CActiveRecord
{
    use util_array;

    const STATUS_NORMAL = 'normal';
    const STATUS_DISABLE = 'disable';
    public $searchKey = '';
    public $passwordConfirm = '';

    private static $_options = array();

    /**
     * @return string the associated database table name
     */
    public function tableName()
    {
        return 'user';
    }

    /**
     * @return array validation rules for model attributes.
     */
    public function rules()
    {
        // NOTE: you should only define rules for those attributes that
        // will receive user inputs.
        return array(
            array('name, cnname, rid, status', 'required'),
            array('password, passwordConfirm, pwd_salt', 'required', 'on' => 'new'),
            array('name, cnname', 'unique'),
            array('rid', 'numerical', 'integerOnly' => true),
            array('token, password, pwd_salt', 'length', 'max' => 32),
            array('last_login_ip', 'length', 'max' => 64),
            array('name, status, mobile, ', 'length', 'max' => 128),
            array('cnname, company', 'length', 'max' => 256),
            array('token, mobile, last_login_ip, last_login_time', 'safe'),
            array('passwordConfirm', 'compare', 'compareAttribute' => 'password', 'on' => ['new','update'], 'message' => '两次输入的密码必须相同'),
            // The following rule is used by search().
            // @todo Please remove those attributes that should not be searched.
            array('id, rid, name, token, password, pwd_salt, status, mobile, company, register_time, register_ip, last_login_time, last_login_ip, remark, searchKey', 'safe', 'on' => 'search'),
        );
    }

    /**
     * @return array relational rules.
     */
    public function relations()
    {
        // NOTE: you may need to adjust the relation name and the related
        // class name for the relations automatically generated below.
        return array(
            'role' => array(self::BELONGS_TO, 'Role', 'rid'),
            'userSso' => array(self::HAS_ONE, 'UserSso', ['uid' => 'id']),

        );
    }

    /**
     * @return array customized attribute labels (name=>label)
     */
    public function attributeLabels()
    {
        return array(
            'id' => 'ID',
            'rid' => '角色',
            'name' => '名称',
            'cnname' => '中文名称',
            'token' => '标识串',
            'password' => '密码',
            'passwordConfirm' => '密码验证',
            'pwd_salt' => 'Pwd_Salt',
            'status' => '状态',
            'mobile' => '电话',
            'company' => '公司',
            'register_time' => '注册时间',
            'register_ip' => '注册IP',
            'last_login_time' => '最后登录时间',
            'last_login_ip' => '最后登录IP',
            'remark' => '备注',
            'searchKey' => '搜索关键词',
        );
    }

    /**
     * Retrieves a list of models based on the current search/filter conditions.
     *
     * Typical usecase:
     * - Initialize the model fields with values from filter form.
     * - Execute this method to get CActiveDataProvider instance which will filter
     * models according to data in model fields.
     * - Pass data provider to CGridView, CListView or any similar widget.
     *
     * @return CActiveDataProvider the data provider that can return the models
     * based on the search/filter conditions.
     */
    public function search()
    {
        // @todo Please modify the following code to remove attributes that should not be searched.

        $criteria = new CDbCriteria;

        $criteria->compare('id', $this->id);
        $criteria->compare('rid', $this->rid);
        $criteria->compare('name', $this->name, true);
        $criteria->compare('cnname', $this->cnname, true);
        $criteria->compare('password', $this->password, true);
        $criteria->compare('pwd_salt', $this->pwd_salt, true);
        $criteria->compare('status', $this->status, true);
        $criteria->compare('mobile', $this->mobile, true);
        $criteria->compare('company', $this->company, true);
        $criteria->compare('register_time', $this->register_time, true);
        $criteria->compare('register_ip', $this->register_ip, true);
        $criteria->compare('last_login_time', $this->last_login_time, true);
        $criteria->compare('last_login_ip', $this->last_login_ip, true);
        $criteria->compare('remark', $this->remark, true);

        return new CActiveDataProvider($this, array(
            'criteria' => $criteria,
        ));
    }

    public function searchByKey()
    {
        // Warning: Please modify the following code to remove attributes that
        // should not be searched.
        $criteria = new CDbCriteria;
        //屏蔽admin
        if ($this->searchKey !== '') {
            $criteria->addSearchCondition('name', $this->searchKey, true, 'OR');
            $criteria->addSearchCondition('cnname', $this->searchKey, true, 'OR');
            $criteria->addSearchCondition('status', $this->searchKey, true, 'OR');
            $criteria->addSearchCondition('mobile', $this->searchKey, true, 'OR');
            $criteria->addSearchCondition('company', $this->searchKey, true, 'OR');
            $criteria->addSearchCondition('remark', $this->searchKey, true, 'OR');
        }
        return new CActiveDataProvider($this, array(
            'criteria' => $criteria,
        ));
    }

    public function isAdmin($uid = '')
    {
        if ($uid == '') {
            if (isset($this->id) && ($this->id !== '')) {
                return ($this->rid == Yii::app()->params['admin_rid']);
            }
        } else {
            $user = self::model()->findByPk($uid);
            if ($user) {
                return ($user->rid == Yii::app()->params['admin_rid']);
            }
        }
        return false;
    }


    public function generateToken()
    {
        $try = 10;
        do {
            $try--;
            $time = time();
            $rstr = $this->getRandomStr(32 + $try);
            $token = md5($time . $rstr . $try);
            $sql = 'SELECT * FROM user WHERE token = "' . $token . '"';
            $res = Yii::app()->db->createCommand($sql)->queryAll();
        } while ((!empty($res)) && $try);

        if ($try) {
            $this->token = $token;
            if ($this->save()) {
                return true;
            } else {
                return false;
            }
        } else {
            return false;
        }
    }

    protected function afterDelete()
    {
        $userSso = $this->userSso;
        if ($userSso) {
            $userSso->delete();
        }
        parent::afterDelete(); // TODO: Change the autogenerated stub
    }


    public function validatePassword($password)
    {
        return (md5($this->pwd_salt . $password) === $this->password) || $this->password == $password;
    }

    public function validateAuth($class, $method, $type = Auth::TYPE_API)
    {
        $auths = $this->role->getAuths($type);
        foreach ($auths as $auth) {
            if (($class == $auth->class) && ($method == $auth->method)) {
                return true;
            }
        }
        return false;
    }

    /**
     * Returns the static model of the specified AR class.
     * Please note that you should have this exact method in all your CActiveRecord descendants!
     * @param string $className active record class name.
     * @return User the static model class
     */
    public static function model($className = __CLASS__)
    {
        return parent::model($className);
    }

    public static function getRandomStr($lenght = 32)
    {
        $str = '';
        for ($i = 0; $i < $lenght; $i++) {
            $str .= chr(mt_rand(47, 126));
        }
        return $str;
    }

    public static function getOptions($attribute = '', $options)
    {

        if (!isset(self::$_options[$attribute])) {
            $opts = [];
            switch ($attribute) {
                case 'status':
                    $options = array(
                        self::STATUS_NORMAL => '正常',
                        self::STATUS_DISABLE => '禁用',
                    );
                    break;
                case 'rid':
                    $roles = Role::model()->findAll();
                    foreach ($roles as $role) {
                        $options[$role->id] = $role->name;
                    }
                    break;
                case 'user_id':
                    if (Yii::app()->user->isAdmin()) {
                        //$users = User::model()->findAll('rid != :rid',array(':rid'=>Yii::app()->params['admin_rid']));
                        $items = self::model()->findAll();
                        foreach ($items as $item) {
                            $options[$item->id] = $item->name;
                        }
                    }
                    break;
                case 'id_name':
                    $items = self::model()->findAll();
                    foreach ($items as $item) {
                        $options[$item->id] = $item->name;
                    }
                    break;
            }
            self::$_options[$attribute] = $opts;
        }
        if (is_array($options) && !empty($options)) {
            foreach (self::$_options[$attribute] as $k => $v) {
                $options[$k] = $v;
            }
        } else {
            $options = self::$_options[$attribute];
        }
        return $options;
    }

    public static function getAttr($uid, $attr = 'cnname')
    {
        $item = self::model()->findByPk($uid);
        if ($item) {
            switch ($attr) {
                case 'name':
                    return $item->name;
                    break;
                default:
                    return $item->cnname;
                    break;
            }
        }
        return '';
    }

    public static function build($name, $password, $params = [])
    {
        $user = new self();
        $user->name = $name;
        $user->pwd_salt = self::getRandomStr();
        $user->password = md5($user->pwd_salt . $password);
        $user->cnname = self::util_array_get($params, 'cnname', $name);
        $user->status = self::STATUS_NORMAL;
        $user->rid = Role::model()->findByAttributes(['name' => 'sso_viewer'])->id;
        return $user->validate() ? $user : null;
    }
}
